Обзор базовых инструментов для тематического моделирования текстовых коллекций





Романенко Александр (МФТИ (ГУ))
aleksandr.romanenko@phystech.edu



ВМК МГУ, 17.02.2017

Предисловие

Задача тематизации и рекомендации контента Постнауки: https://www.postnauka.ru

О чем эта лекция?

  • Работа с текстовыми коллекциями: опыт и практические советы
  • Рекоммендации по планированию экспериментов
  • Базовые возможности библиотеки BigARTM
  • Анализ построенной тематической модели: инструменты и советы

Зачем эта лекция?

Правильная подготовка экспериментов позволяет (или может позволить) добиться:

  • улучшения получаемых результатов
  • ускорения экспериментов (увеличения их количества) => п. 1
  • воспроизводимости экспериментов
  • удобной интерпретации и презентации результатов
  • возможности понимания и повторения эксперимента другими людьми с минимальным участием экспериментатора

Структура изложения

  1. Предобработка данных
  2. Построение моделей
  3. Анализ результатов

Предобработка данных

"Сейчас быстро перегоню тексты в Vowpal Wabbit, и надо пробовать строить модели..."

Если эксперимент пилотный или тестовый - ОК.
Если эксперимент в рамках проекта - так делать НЕЛЬЗЯ.

Невнимательное отношение к данным может привести к печальным последствиям (не только в ТМ, но и вообще в ML). Для правильного построения дальнейшей работы важно:

  • корректно преобразовать данные в понимаемый Вами формат.
  • изучить структуру данных, статистические характеристики и проч.

Форматы данных бывают какие угодно:

  • База данных или её дамп.
  • Наборы текстовых файлов или один файл с текстами.
  • То же самое в json/xml/protobuf...
  • Могут быть вообще сырые pdf, html...

Внутри каждого описанного типа данные могут иметь совершенно произвольный вид, то есть написать универсальный парсер данных в Vowpal Wabbit невозможно.

Задача парсинга ложится на пользователя.

Совет: нужно внимательно посмотреть на данные, поискать особенности и ошибки в самих данных!

Как можно посмотреть на данные?

  • Можно прямо из Python
    with [codecs.]open(data_filename ...).
    При поиске закономерностей удобно использовать регулярные выражения (модуль re)
    Помните: для стандартных форматов: json, xml, дампы баз данных есть готовые модули для работы, не тратьте время на изобретение велосипедов.
  • В Linux/Mac OS можно пользоваться разными терминальными командами: less, head, tail.
  • В Windows удобно использовать графический редактор EmEditor (позволяет открывать гигантские файлы, таблицы, умеет работать с tab-ами и запятыми).

Совет: преобразования данных лучше проводить поэтапно, сохраняя промежуточные результаты

Данные надо поправить так, чтобы:

  • все компоненты легко отделялись друг от друга (раздельные сеператоры внутри групп и между группами).
  • все неполные данные были либо дополнены какими-то значениями, либо удалены из выборки.
  • все ненужные данные должны быть удалены.

Если данных много, и из общей схемы парсинга выбиваются доли процента от числа документов -- можно их выбросить и не тратить время.

Пример: коллекция постов Постнауки

In [4]:
import glob

filelist = glob.glob('./data/files/*')
print(u"Число документов: {}".format(len(filelist)))
print filelist[:5]
Число документов: 3446
['./data/files/21617.txt', './data/files/28563.txt', './data/files/48957.txt', './data/files/9728.txt', './data/files/54464.txt']
In [5]:
import codecs
with codecs.open(filelist[0],'r','utf-8') as f:
    lines = []
    for line in f:
        lines += [line.strip()]
    doc = u" ".join(lines)
print doc
Биомедицинская диагностика ------------------------------------------------------------------------------ Химик Евгений Гудилин о диагностике по единичным клеткам и гигантском комбинационном рассеянии ------------------------------------------------------------------------------ Какие существуют методы неинвазивной диагностики? Как возникает явление плазмонного резонанса? И как возможна биомедицинская диагностика без разрушения исследуемых клеток? Об этом рассказывает доктор химических наук Евгений Гудилин.

Основные этапы предобработки

  • Нормализация текста
  • Выделение в тексте n-gramm (термины, именованные сущности, коллокации и т.д.)
  • Работа со словарем коллекции и самой коллекцией
  • Конвертация в один их поддерживаемых BigARTM форматов

Нормализация текста

  • перевод текста в нижний регистр
  • токенизация - разделение текста на токены, элементарные единицы текста
  • стемминг/лемматизация - приведение токенов к некой унифицированной начально форме

Токенизация

  • средства NLTK: nltk.tokenize
  • по правилам (разделение по пробелам и знакам пунктуации)

Пример. Русский язык

In [3]:
import re

# для русского языка
text_ru = doc.lower()
text_ru = re.sub(u'([^a-zа-яё]+)',u' \\1 ',text_ru.lower())
text_ru =  re.sub(u"\s+",u" ", text_ru).strip()
print text_ru.replace(u' ',u'|')
биомедицинская|диагностика|------------------------------------------------------------------------------|химик|евгений|гудилин|о|диагностике|по|единичным|клеткам|и|гигантском|комбинационном|рассеянии|------------------------------------------------------------------------------|какие|существуют|методы|неинвазивной|диагностики|?|как|возникает|явление|плазмонного|резонанса|?|и|как|возможна|биомедицинская|диагностика|без|разрушения|исследуемых|клеток|?|об|этом|рассказывает|доктор|химических|наук|евгений|гудилин|.

Пример. Английский язык

In [4]:
# для английского языка
text_en = u"Where is your spoon, daddy?"
text_en = re.sub(u'([^a-z]+)',u' \\1 ',text_en.lower())
text_en =  re.sub(u"\s+",u" ", text_en).strip()
print text_en.replace(u' ',u'|')
where|is|your|spoon|,|daddy|?

Стемминг

СТЕММИНГ - нормализация слов путем отбрасывания окончаний (согласно правилам, основанным на грамматике языка)

Стеммеры (nltk)

Примеры работы стеммеров:

машины -> машин
дело -> дел
гости -> гость

loving -> love
stemming -> stem
says -> say
why -> whi

Лемматизация

Лемматизация - приведение слов к начальной морфологической форме (с помощью словаря и грамматики языка)

Лемматизаторы

  • pymorphy2 (язык русский, украинский)
  • mystem3 (язык русский, английский?)
  • Wordnet Lemmatizer (NLTK, язык английский, требует POS метку)
  • Metaphraz (язык русский)
  • Lemmatizer.org (сайт уже не существует... язык русский)
  • Coda/Cadenza (языки русский и английский)

Пример. Английский язык

In [11]:
import codecs
import pymorphy2
import nltk
from nltk.corpus import wordnet
from nltk.stem import WordNetLemmatizer

def get_wordnet_pos(treebank_tag):

    if treebank_tag.startswith('J'):
        return wordnet.ADJ
    elif treebank_tag.startswith('V'):
        return wordnet.VERB
    elif treebank_tag.startswith('N'):
        return wordnet.NOUN
    elif treebank_tag.startswith('R'):
        return wordnet.ADV
    else:
        return wordnet.NOUN
In [12]:
wnl = WordNetLemmatizer()

doc = text_en.split(u" ")
print [wnl.lemmatize(w,get_wordnet_pos(pos)) for w,pos in nltk.pos_tag(doc)]
[u'where', u'be', u'your', u'spoon', u',', u'daddy', u'?']

Пример. Русский язык

In [19]:
pymorph = pymorphy2.MorphAnalyzer()
temp = []
for word in text_ru.split(u' '):
    if not re.match(u'([^a-zа-яё]+)',word):
        word = pymorph.parse(word)[0].normal_form
    temp += [word]
print u"|".join(temp)
биомедицинский|диагностика|------------------------------------------------------------------------------|химик|евгений|гудилин|о|диагностик|по|единичный|клетка|и|гигантский|комбинационный|рассеяние|------------------------------------------------------------------------------|какой|существовать|метод|неинвазивный|диагностика|?|как|возникать|явление|плазмонный|резонанс|?|и|как|возможный|биомедицинский|диагностика|без|разрушение|исследовать|клетка|?|о|это|рассказывать|доктор|химический|наука|евгений|гудилин|.

Выделение энграмм

Можно выделять:

  • термины
  • именованные сущности (person, location, date, organization, ...)
  • коллокации - словосочетания, имеющие признаки синтаксически и семантически целостных единиц

Как это можно делать:

  • С помощью словарей n-gramm
  • ML алгоритмы сегментации и разметки последовательностей (HMM, MEMM, CRF, RNN, LSTM), настроенные на конкретную задачу
  • Энграммер Царькова Сергея
  • Статистическое выделение n-gramm. Например, объединение 2-х униграмм в биграмму по порогу PMI.

Ngrammer по мотивам статьи El-Kishky et al, Scalable Topical Phrase Mining from Text Corpora // 2014
Мой код. Что реализовано:

  • возможность задавать максимальную длину n энграммы
  • с помощью двух гиперпараметров можно подкрутить точность/полноту выделения энграмм
  • возможность "дообучиться" - собрать в энграммер статистику по нескольких корпусам
  • возможность сохранить и загрузить с диска состояние энграммера
  • можно задать список токенов, которые не могут входить в энграммы (стоп-слова)
  • можно задать список регулярных выражений, описывающих токены, которые не могут входить в энграммы (пунктуация)
In [ ]:
import os
os.sys.path.append("/home/alex/workspace/tm_nlp/")
from tools import ngrammer

ng = ngrammer.NGrammer()

delimiters = loadFileAsStringArray('stop-words-ru.txt')
ng.delimiters = delimiters # delimiters - это list или dict содержащий слова разделители

delimiters_regex = [u'[^a-zа-яё ]+']
ng.delimiters_regex = delimiters_regex # delimiters_regex - это список regex, описывающий разделители

ng.frequentPhraseMining(corpus_text,threshhold=15,max_ngramm_len=5) # собираем статистику по корпусу текстов corpus_text
ng.saveAsJson('ngrammer_stat.txt',True) # сохраняем состояние энграммера

ng = ngrammer.NGrammer() 
ng.loadFromJson('ngrammer_stat.txt',True) # загружаем предварительно сохраненное состояние из файла

res = ng.ngramm(doc, threshhold=5.0) # обрабатываем документ doc. threshhold - порог, который можно покрутить
res = ng.removeDelimiters(res) # можно выкинуть из результата работы слова разделители

Примеры энграмм:

1741 - точка зрение
700 - чёрный дыра
689 - русский язык
563 - речь идти
510 - xx век
476 - крайний мера
464 - xix век
462 - большой количество
440 - друг друг
434 - дать случай
392 - нейтронный звезда
381 - огромный количество
364 - мировой война
297 - элементарный частица

202 - начало xx век
191 - собрать хороший выступление
169 - рассказывать доктор физикий
127 - общий теория относительность
99 - конец xix век
97 - большой адронный коллайдер
89 - физика элементарный частица
78 - вопрос отвечать кандидат
72 - сверхмассивный чёрный дыра
70 - середина xix век

Анализ коллекции и словаря

Итак, мы сделали предобработку коллекции: токенизировали, лемматизировали текст, выделили ngramm'ы, сохранили все это в удобном и понятном формате.

Теперь надо посчитать и изучить различные статистики корпуса, подготовить коллекцию в целом для тематического моделирования

Базовые вещи, на которые всегда надо смотреть:

  • Число документов в коллекции.
  • Объём словаря.
  • Распределение длин документов, средняя длина документа.
  • Суммарная длина коллекции.

Мой код. Класс Collection позволяет выполнять основные действия с коллекциями

Входные форматы данных:

  • UCI
  • Набор файлов. Представление документа - это одна строка. Элементы словаря разделены пробелами. Шаблон имен файлов:
    `имя_коллекции.имя_модальности.postfix`
    Например:
    pn.ngramm.txt

Загружаем коллекцию

In [76]:
from tools import Collection
# конструктор может быть пустой или принимать пути до файлов vocab или docword UCI формата
collection = Collection.Collection()
collection.verbose = True
collection.load_split_modality_files('pn','./data/pn_all/')
print "Длина словаря:",collection.get_vocabulary().size()
Длина словаря: 95341

Считаем частоты слов

In [77]:
tf_df = collection.tf_df('ngramm')
tf_df = sorted(tf_df.items(),key=lambda x:x[1][0],reverse=True)
voc = collection.vocabulary
for k,v in tf_df[:40]:
    print u"{0:<40}{1}".format(voc.get_word(k)[0],v[0])
,                                       370962
.                                       179880
в                                       127488
и                                       113111
что                                     51140
это                                     48539
на                                      43543
не                                      42062
с                                       38524
быть                                    35561
который                                 35002
-                                       32130
—                                       31974
как                                     28696
«                                       28346
то                                      27953
мы                                      26547
он                                      25389
они                                     24307
тот                                     23930
этот                                    23541
о                                       22151
а                                       18939
к                                       18929
но                                      18171
весь                                    17854
один                                    17690
из                                      17364
по                                      16957
мочь                                    16464
:                                       16359
для                                     16250
такой                                   15464
человек                                 14372
или                                     14337
есть                                    14001
(                                       13654
год                                     13592
?                                       13397
»                                       13052

Закон Ципфа, распределение частот слов

In [78]:
import matplotlib.pyplot as plt
%matplotlib inline

plt.plot([tf[1][0] for tf in tf_df[:100]],linewidth=2)
plt.ylabel(u'Frequency')
plt.xlabel(u'Rank')
plt.title(u"Zipf's law")
Out[78]:
<matplotlib.text.Text at 0x7fe9ccd51e90>

Закон Хипса, статистика по линам документов

In [79]:
len2len = {}
for doc_id in collection.docword:
    bow = collection.get_document(doc_id,None,doc_type='BOW')
    len2len.setdefault(sum(bow.values()),[])
    len2len[sum(bow.values())] += [len(bow)]
srtd_len = sorted(len2len.items(),key=lambda x: x[0])
In [82]:
doc_len1 = [x[0] for x in srtd_len]
doc_len2 = [sum(x[1])/len(x[1]) for x in srtd_len]
plt.plot(doc_len1,doc_len2,linewidth=2)
plt.ylabel(u'# distinct tokens')
plt.xlabel(u'Length of document')
plt.title(u"Heaps' law")
Out[82]:
<matplotlib.text.Text at 0x7fe959a7cd10>

Гистограмма распределения длин документов коллекции

In [32]:
import numpy as np
X = np.arange(len(len2len))
plt.bar(X, [len(x) for x in len2len.values()], align='center', width=0.5)
plt.xticks(np.arange(1, len(len2len.keys()), len(len2len.keys()) / 5))
ymax = max([len(x) for x in len2len.values()]) + 1
plt.ylim(0, ymax)
plt.xlabel(u'Length of document')
plt.ylabel(u'# of documents')
# plt.show()
Out[32]:
<matplotlib.text.Text at 0x7fe9849e11d0>

Фильтруем словарь

Удаление стоп-слов

Какие бывают стоп-слова

  • Стоп-слова языка
  • Стоп-слова коллекции
  • Стоп-энграммы
In [36]:
stopwords = {}
with codecs.open('stopwords-ru_pymorphy.txt','r','utf-8') as f:
    for line in f:
        stopwords[line.strip()] = 1
In [37]:
regex = re.compile(u'[^a-zа-яё ]+')
min_tf = 6
max_tf = 5000
min_length = 3
max_length = 20
to_remove = []
for idx,[tf,df] in tf_df:
    word = voc.get_word(idx)[0]
    if tf <= min_tf or tf >= max_tf \
            or len(word) <= min_length or len(word) > max_length \
            or regex.match(word) or stopwords.has_key(word):
        to_remove += [idx]
print "Число документов на удаление:", len(to_remove)
Число документов на удаление: 70907
In [38]:
collection.remove_words(to_remove)
print "Длина словаря:",collection.get_vocabulary().size()
Длина словаря: 24434

Удаляем очень короткие документы

In [58]:
len2len = {}
min_length = 30
to_remove = []
for doc_id in collection.docword:
    doc = collection.get_document(doc_id,None)
    if doc.length() < min_length:
        to_remove += [doc_id]
print "Число документов на удаление:", len(to_remove)
Число документов на удаление: 279
In [59]:
collection.remove_documents(to_remove)
print "Длина коллекции в документах:",collection.size()
Длина коллекции в документах: 3167

После фильтрации словаря и документов

In [60]:
tf_df = collection.tf_df('ngramm')
tf_df = sorted(tf_df.items(),key=lambda x:x[1][0],reverse=True)

plt.plot([tf[1][0] for tf in tf_df[:200]],linewidth=2)
plt.ylabel(u'Frequency')
plt.xlabel(u'Rank')
plt.title(u"Zipf's law")
Out[60]:
<matplotlib.text.Text at 0x7fe9619c3c90>

Сохраняем коллекцию в Vowpal Wabbit формате

In [61]:
collection.save_as_vw(filename='data/vw/vw_bow.txt',
                      vocab_filename='./data/vw/vocab.txt',bow=True)
collection.save_as_vw(filename='data/vw/vw.txt',
                      vocab_filename='./data/vw/vocab.txt',bow=False)

Моделирование

Планирование эксперимента

Какой нужен код

  • Код по загрузке данных
  • Код для журналирования результатов экспериментов.
  • Код для моделирования.

Стоит описать функции единообразного создания, обучения и оценки модели.

  1. меньше кода.
  2. удобнее.
  3. меньше шансов ошибиться и проще искать ошибку и модернизировать.
In [ ]:
def create_model(num_topics, num_processors, params, ...):
    ...
    return model

def train_model(model, num_collection_passes, params, ...):
    ...
    return model

def evaluate_model(model, params, ...):
    ...
    return scores

Стоит описать функцию единообразного сохранения результатов эксперимента.

  1. меньше кода.
  2. удобнее.
  3. меньше шансов ошибиться и проще искать ошибку и модернизировать.

Совет: сохраняйте абсолютно всю информацию, относящуюся к эксперименту.

In [ ]:
def save_results(model_name, model, params, scores, elapsed_times, top_words, out_filename, ...):

Внимательно и понятно описывайте параметры экспериментов

In [2]:
params = {}
params['model_name'] = 'postnauka_plsa_200_topics'
params['num_topics'] = 200
params['num_processors'] = 7
params['num_collection_passes'] = 30
...

Пример кода эксперимента:

In [ ]:
params = {}
params['model_name'] = 'postnauka_plsa_200_topics'
params['num_topics'] = 200
params['num_processors'] = 7
params['num_collection_passes'] = 30
...

model = create_model(params,...)
time_start = time.time()
model = train_model(model,params,...)
time_end = time.time()
scores = evaluate_model(model, ...)
save_results(model, params, scores, time_start-time_end, '{}_res.txt'.params['model_name'])

BigARTM

BigARTM - библиотека тематического моделирования, в которой реализованы основные алгоритмы и функции работы с тематическими моделями.

Внутри BigARTM - обобщенный EM-алгоритм для любого типа моделей.

Структура библиотеки:

  • Ядро на C++
  • Интерфейсы: command line, C++, python
  • Передача данных между ядром и интерфейсом: protobuf

Ключевые особенности:

  • Эффективность [Big]:
    • Параллельная обработка данных (multithread)
    • Необходимость хранения только матрицы $\Phi$, матрицу $\Theta$ хранить необязательно
  • Богатая встроенная библиотека регуляризаторов и метрик качества [AR]
  • Поддержка многомодальных тематических моделей [TM]

Установка

Документация: http://docs.bigartm.org/en/stable/

Документация по установке: http://docs.bigartm.org/en/stable/installation (см. свою ОС)

Этапы установки:

  1. Python 2/3 + numpy, pandas
  2. Скачать релиз / git clone
  3. Установка protobuf
  4. Для Linux / Mac OS: компиляция ядра
  5. Установка python-модуля artm
  6. Добавление artm/bin в PATH (или создание ARTM_SHARED_LIBRARY), artm/python в PYTHONPATH

Также можно воспользоваться образом docker: https://github.com/bigartm/bigartm-docker

Видеоинструкция по установке (для версии BigARTM 0.7.4):

Документация к python интерфейсу: http://docs.bigartm.org/en/stable/tutorials/python_tutorial.html

Формат входных данных

Оформление файла с данными

Наиболее удобный формат: vowpal wabbit - специальная разметка txt-файла:

  • каждая строка - один документ
  • первое слово в строке - название документа
  • далее через пробел следуют пары слово:количество (слова могут повторяться, :1 можно опускать, счетчики суммируются)
  • |слово - название модальности (после него следуют слова этой модальности)
  • если название модальности не указано, слова относятся к модальности @default_class

Наиболее простой пример:

 тематическое моделирование это метод статистический анализ текстовый коллекция

Пример:

Лекция1 |@text тематическое моделирование это метод статистический анализ текстовый коллекция:2 представляться матрица частота слово

Импорт данных

BigARTM преобразует данные во внутренний формат - батчи. Батчи сохраняются в заданную директорию и управляются объектом класса BatchVectorizer.

In [65]:
import artm 

source_file = os.path.join("data/vw", "vw.txt")
batches_folder = "data/batches"
if not glob.glob(os.path.join(batches_folder, "*")):
    batch_vectorizer = artm.BatchVectorizer(data_path=source_file, data_format="vowpal_wabbit", 
                                            target_folder=batches_folder, batch_size=400)
else:
    batch_vectorizer = artm.BatchVectorizer(data_path=batches_folder,
                                            data_format='batches')

Сбор словаря

In [66]:
dict_name = os.path.join(batches_folder, "dictionary.dict")
dictionary = artm.Dictionary()
if not os.path.exists(dict_name):
    dictionary.gather(batches_folder)
    dictionary.save(dict_name)
else:
    dictionary.load(dict_name)

Построение модели

Объявление метрик качества, снимаемых с моделей

Perplexity (Перплексия)

Перплексия - это мера несоответствия или «удивлённости» модели $p(w|d)$ терминам $w$, наблюдаемым в документах $d$ коллекции $D$, определяемая через логарифм правдоподобия: $$P(D,d)=\exp(-\frac{1}{n}L(\Phi,\Theta))=\exp(-\frac{1}{n}\sum_{d\in D}\sum_{w\in d}n_{dw}\ln{p(w|d)}).$$

In [68]:
scores_list = []
scores_list.append(artm.PerplexityScore(name='PerplexityScore'))  # перплексия (перенормированное правдоподобие)
scores_list.append(artm.TopTokensScore(name="top_words", 
                                          num_tokens=15, 
                                          class_id="ngramm"))  # для печати наиболее вероятных терминов темы
                                                                           

Создаем модель

In [69]:
T = 30   # количество тем
model_artm = artm.ARTM(num_topics=T,  # число тем
                       class_ids={"ngramm":1},   # число после названия модальностей - это их веса
                       num_document_passes=10,   # сколько делать проходов по документу
                       cache_theta=True,   # хранить или нет глоабльную матрицу Theta
                       reuse_theta=False,   # если Theta хранится, нужно ли ее вновь инициализировать при каждом проходе
                       theta_columns_naming="title",   # как именовать столбцы в матрице Theta
                       seed=789,   # random seed
                       scores=scores_list)  # метрики качества

Модель нужно инициализировать с помощью словаря. Затем мы сможем ее обучить:

In [70]:
model_artm.initialize(dictionary)

Обучение модели

In [71]:
%time model_artm.fit_offline(batch_vectorizer=batch_vectorizer, num_collection_passes=30)
CPU times: user 1min 27s, sys: 136 ms, total: 1min 27s
Wall time: 33.6 s

Изменение перплексии в зависимости от номера прохода по коллекции

In [72]:
plt.plot(model_artm.score_tracker["PerplexityScore"].value[1:]) 
Out[72]:
[<matplotlib.lines.Line2D at 0x7fe9cca36790>]
In [73]:
print "Perplexity:", model_artm.score_tracker["PerplexityScore"].last_value
Perplexity: 3081.28157944

Выведем списки топ-слов

In [74]:
for topic_name in model_artm.topic_names:
    print topic_name + ': ',
    for word in model_artm.score_tracker["top_words"].last_tokens[topic_name]:
        print word,
    print
topic_0:  частица кварк масса энергия протон симметрия эксперимент электрон нейтрино взаимодействие ускоритель являться стандартный_модель теория состоять
topic_1:  материал атом структура свет вещество использовать являться электрон система свойство метод устройство энергия элемент состояние
topic_2:  книга наука автор работа метр история читать написать текст писать читатель тема исследование заниматься литература
topic_3:  философия текст философ говорить идея культура философский образ мысль платон искусство являться традиция должный смысл
topic_4:  пространство теория вселенная математика уравнение точка являться физик математический физика эйнштейн квантовый число описывать закон
topic_5:  сеть интернет дать раса тысяча пользователь неандерталец современный исследователь найти антропология связь друг антрополог исследование
topic_6:  история музей прошлое память историк театр исторический русь стать образ событие знать представление документ князь
topic_7:  город царь территория япония государство страна москва земля место центр история большой остров вулкан жить
topic_8:  университет наука учёный должный образование студент хороший работать работа заниматься большой деньга школа говорить научный
topic_9:  герой русский искусство мода святилище советский роман праздник авангард писать тело говорить сказка обряд образ
topic_10:  клетка пациент заболевание болезнь врач препарат лечение медицина ткань являться больной организм система мутация боль
topic_11:  социология социальный объект социолог пространство отношение теория сообщество являться исследование общество действие социологический наука теоретический
topic_12:  событие теория движение декарт эффект система гипотеза трудность состояние объяснение образ являться происходить описание модель
topic_13:  право россия власть закон лекция король прочитать государство император правовой политический публиковать выбирать postnauka должный
topic_14:  остров сага ирландия церковь тинг король сокотра ведьма знать ирландский образ страна корабль текст история
topic_15:  животное самец поведение самка группа растение эмоция эволюция птица признак большой насекомое отбор некоторый механизм
topic_16:  страна экономика экономический китай рынок россия кризис государство компания стать цена большой проблема население развитие
topic_17:  язык культура народ территория традиция говорить существовать история группа называть восток христианство восточный письменность являться
topic_18:  язык слово говорить русский_язык словарь лингвист текст русский речь разный значение глагол буква звук знать
topic_19:  война сталин страна германия власть партия политический советский стать военный немецкий государство мировой_война революция политика
topic_20:  мозг нейрон память процесс мышление сознание исследование задача связь происходить активность информация область образ проблема
topic_21:  ребёнок женщина мужчина жизнь pcourse семья отношение общество социальный родитель проблема работа стать группа исследование
topic_22:  объект видеть глаз предмет восприятие говорить жест знать смотреть образ лицо форма рука информация изображение
topic_23:  фильм политический государство понятие свобода общество являться культура говорить политика смысл современный кино демократия должный
topic_24:  земля планета солнце жизнь марс планет космос метеорит атмосфера большой астероид занятие поверхность орбита космический
topic_25:  клетка молекула белка белок геном бактерия организм вирус структура происходить процесс разный работать образ мембрана
topic_26:  задача дать система решение модель компьютер программа информация результат алгоритм работать работа компания оценка использовать
topic_27:  город пространство здание архитектура дискурс образ городской роль являться форма книга жизнь культура работа отношение
topic_28:  звезда галактика вселенная чёрный_дыра объект вещество большой масса нейтронный_звезда планета наблюдение расстояние солнце излучение размер
topic_29:  микроорганизм организм робот кислород вода жизнь процесс использовать микроб земля являться условие растение существовать исследование

VisARTM

Для анализа более полного анализа модели хочется:

  • cмотреть на топ-слова тем и их вероятности
  • cмотреть на документы с максимальным значением $p(t|d)$ для темы
  • cмотреть на тематические профили документов $p(t|d)$
  • cмотреть на тематические профили слов $p(w|t)$ и/или $p(t|w)$
  • cмотреть на тематические профили каждого слова в каждом документе $p(t|w,d)$
  • видеть похожие документы согласно p(t|d)
  • видеть похожие темы согласно p(w|t)
  • строить другие всевозможные визуализации...

Основные возможности VisARTM:

  • Работа с датасетами
    • Несколько форматов данных (и метаданных)
    • Опциональная предобработка текстов
    • Автоматический сбор статистики по данным
    • Конвертация данных в формат BigARTM
  • Возможность построения ТМ на веб-сервере (BigARTM)
  • Визуализации темпоральных и иерархических ТМ
  • Возможность модульного добавления визуализаций

Технические подробности:

  • Python 3.4+, Django
  • BigARTM
  • PostgresQL

Полезные ссылки: